#include"../common/net.hpp"
#include"../common/message.hpp"
#include<future>
#include<unordered_map>
#include<functional>
namespace bitRPC {
    namespace client{
        class Requestor{
            public:
                using ptr=std::shared_ptr<Requestor>;
                using RequestCallback=std::function<void (const BaseMessage::ptr&)>;
                using AsyncResponse=std::future<BaseMessage::ptr>;
                struct RequestDescrible{
                    using ptr=std::shared_ptr<RequestDescrible>;
                    BaseMessage::ptr resqust;
                    RType rtype;
                    std::promise<BaseMessage::ptr> response;
                    RequestCallback callback;
                };
                void onResponse(const BaseConnection::ptr& conn,BaseMessage::ptr& msg)
                {
                    std::string rid=msg->Rid();
                    RequestDescrible::ptr rdp=getDesecriible(rid);
                    if(rdp.get()==nullptr)
                    {
                        ELOG("收到响应，-%s 但未找到对应的请求描述！",rid.c_str());
                        return ;
                    }else if(rdp->rtype==RType::RPC_CALLBACK)
                    {
                        if(rdp->callback)
                        {
                            rdp->callback(msg);
                        }
                    }else if(rdp->rtype==RType::RPC_ASYNC)
                    {
                        rdp->response.set_value(msg);
                    }else {
                        ELOG("请求类型未知");
                    }
                    delDescribe(rid);
                }
                bool send(const BaseConnection::ptr& conn,const BaseMessage::ptr& req,AsyncResponse &async_rsp)
                {
                    RequestDescrible::ptr rdp=newDescrible(req,RType::RPC_ASYNC);
                    if(rdp.get()==nullptr)
                    {
                        ELOG("构造请求描述失败！");
                        return false;
                    }
                    async_rsp=rdp->response.get_future();
                    return true;
                }
                bool send(const BaseConnection::ptr& conn,const BaseMessage::ptr &req,BaseMessage::ptr &rsq)
                {
                    AsyncResponse rsp_futrue;
                    bool ret=send(conn,req,rsp_futrue);
                    if(ret==false)
                    {
                        return false;
                    }
                    rsq=rsp_futrue.get();
                    return true;
                }
                bool send(const BaseConnection::ptr& conn,const BaseMessage::ptr &req,RequestCallback& cb)
                {
                     RequestDescrible::ptr rdp=newDescrible(req,RType::RPC_CALLBACK,cb);
                    if(rdp.get()==nullptr)
                    {
                        ELOG("构造请求描述失败！");
                        return false;
                    }
                    conn->send(req);
                    return true;
                }
            private:
                RequestDescrible::ptr getDesecriible(std::string& rid)
                {
                    std::unique_lock<std::mutex> lock(_mutex);
                    auto ret=_request_desc.find(rid);
                    if(ret==_request_desc.end())
                    {
                        return RequestDescrible::ptr();
                    }
                    return ret->second;
                }
                RequestDescrible::ptr newDescrible(const BaseMessage::ptr &req,RType rtype,RequestCallback cb=RequestCallback())
                {
                    std::unique_lock<std::mutex> lock(_mutex);
                    RequestDescrible::ptr rd=std::make_shared<RequestDescrible>();
                    rd->resqust=req;
                    rd->rtype=rtype;
                    if(rtype==RType::RPC_CALLBACK&&cb)
                    {
                        rd->callback=cb;
                        return rd;
                    }
                }
                void insertDesrcrible(const RequestDescrible::ptr &req)
                {
                    std::unique_lock<std::mutex> lock(_mutex);
                    auto ret=_request_desc.find(req->resqust->Rid());
                    if(ret==_request_desc.end())
                    {
                        ELOG("该请求已经存在");
                        return ;
                    }
                    _request_desc.insert({req->resqust->Rid(),req});

                }
                void delDescribe(const std::string &rid) {
                    std::unique_lock<std::mutex> lock(_mutex);
                    _request_desc.erase(rid);
                }
            private:
                std::mutex _mutex;
                std::unordered_map<std::string,RequestDescrible::ptr> _request_desc;
        };
    }
}